home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
201-225
/
disk_218
/
mandel
/
src
/
misc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
16KB
|
592 lines
/*
* M A N D E L B R O T C O N S T R U C T I O N S E T
*
* (C) Copyright 1989 by Olaf Seibert.
* Mandel may be freely distributed. See file 'doc/Notice' for details.
*
* Main Program, including some general routines
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#ifdef DEBUG
# include <stdio.h>
# undef STATIC
# define STATIC /* EMPTY */
#endif
#include "mandel.h"
extern struct NewWindow XYNWindow;
extern struct Window *XYwindow;
#define BORDERLEFT 3
#define BORDERTOP 11
#define BORDERBOTTOM 3
#define CHARS 16 /* Change UpdateXYwindow also with this */
struct NewWindow XYNWindow =
{
2 * BORDERLEFT, 2 * BORDERTOP,
CHARS*8+BORDERLEFT*2, 2*8+BORDERTOP+BORDERBOTTOM,
2, 1, /* DetailPen, BlockPen */
0, /* CLOSEWINDOW */
WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | SIMPLE_REFRESH,
NULL, /* FirstGadget */
NULL, /* default CheckMark */
(UBYTE *) "Re and Im", /* Title */
NULL, /* Screen */
NULL, /* BitMap */
0, 0, /* MinWidth, MinHeight */
0, 0, /* MaxWidth, MaxHeight */
CUSTOMSCREEN /* Screen type */
};
double ReMouse, ImMouse;
/*
* We always ask for INTUITICKS, since this window will only be open
* as long as we have the flashing lines.
*/
void OpenXYwindow()
{
if (XYwindow == NULL) {
XYNWindow.Screen = MandelScreen;
if (XYwindow = OpenWindow(&XYNWindow)) {
XYwindow->UserPort = MainWindow->UserPort;
ModifyIDCMP(XYwindow, (long)CLOSEWINDOW | MOUSEBUTTONS | INTUITICKS);
SetDrMd(XYwindow->RPort, (long)JAM2);
SetAPen(XYwindow->RPort, (long)1);
SetBPen(XYwindow->RPort, (long)0);
}
}
}
void CloseXYwindow()
{
if (XYwindow) {
CloseWindowSafely(XYwindow);
XYwindow = NULL;
}
}
void UpdateXYwindow(x, y) /* corrected: 0..max */
int x, y;
{
register int chars;
register struct RastPort *rp;
register long left, top;
char buffer[CHARS+2]; /* 1 extra for \0, and 1 for safety */
static char format[] = "%-16.10g"; /* 16 == CHARS */
/* -1.234567890e-99 is 16 chars with a precision of 10 digits */
ReMouse = LeftEdge + CXStep * x;
ImMouse = TopEdge - CYStep * y;
if (XYwindow) {
rp = XYwindow->RPort;
left = XYwindow->BorderLeft;
top = XYwindow->BorderTop;
chars = sprintf(buffer, format, ReMouse);
Move(rp, left, top+7);
Text(rp, buffer, (long)chars);
chars = sprintf(buffer, format, ImMouse);
Move(rp, left, top+15);
Text(rp, buffer, (long)chars);
}
}
void MyExit(status)
char *status;
{
static char message[] = "\
\0\144\25Mandelbrot Construction Set -- By KosmoSoft Productions\0a\
\0\144\41 \0";
/* 3^5^ 10^ ^ 20^ ^ 30^ ^ 40^ ^ 50^ 55^58^ */
register char *c=message+63;
#ifdef AREXX
dnRexxPort();
#endif
if (status) {
/* Center the message. */
{
register int halfway = 320 - (strlen(status) << 2);
message[60] = halfway >> 8; /* High byte */
message[61] = halfway; /* Low byte */
}
while ((*(c++) = *(status++)) && c < message + 127);
*c = 0;
/* Let's be paranoid for a change... */
if (!IntuitionBase) IntuitionBase = (struct IntuitionBase *)
OpenLibrary ("intuition.library", 0L);
if (IntuitionBase)
DisplayAlert(RECOVERY_ALERT, message, 50L);
else { /* AT_Recovery | AG_OpenLib | AO_Intuition */
CPTR AlertParameter = (CPTR) FindTask(NULL);
Alert(0x00038004L, &AlertParameter);
}
status=1;
}
CleanupDisplay((bool) TRUE);
if (DrawSigBit != -1) FreeSignal((long)DrawSigBit);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (LayersBase) CloseLibrary(LayersBase);
if (GfxBase) CloseLibrary(GfxBase);
exit ((int) (status != NULL));
}
void _abort()
{
MyExit("_abort() called...");
}
bool Sure()
{
bool Result;
ULONG OldIDCMP = MainWindow->IDCMPFlags;
static struct IntuiText Body[] =
{
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
25, 10, NULL, (UBYTE *) "You are going to", &Body[1] },
{ MYFRONTPEN+1, AUTOBACKPEN, AUTODRAWMODE,
57, 25, &Topaz60, (UBYTE *) "destroy", &Body[2] },
{ MYFRONTPEN, AUTOBACKPEN, AUTODRAWMODE,
33, 40, NULL, (UBYTE *) "your picture !", NULL }
};
if (Saved) return TRUE;
ModifyIDCMP(MainWindow, OldIDCMP &~ (MENUVERIFY | SIZEVERIFY | REQVERIFY));
Result = AutoRequest(MainWindow, &Body[0], &PositiveText, &NegativeText,
NULL, NULL, 200L, 90L);
ModifyIDCMP(MainWindow, OldIDCMP);
return Result;
}
/*
* Render a requester in a window. If it won't fit, open a new window.
* This new window will share the IDCMP port with the original
* window. This is to save memory, signal bits and VERIFY deadlocks.
* Returns the window in which the requester actually appears.
*/
struct Window *MyRequest(request, window)
struct Requester *request;
struct Window *window;
{
static struct NewWindow newwindow = {
0, 0, 0, 0, 2, 1,
NULL, /* IDCMP flags -- port shared with main window */
WINDOWDEPTH | WINDOWDRAG | ACTIVATE | SIMPLE_REFRESH | NOCAREREFRESH,
NULL, NULL, NULL, NULL,
NULL, 0, 0, 0, 0, NULL };
int width, height;
int borderleft, borderright, bordertop, borderbottom;
struct Window *oldwindow = window;
borderleft = window->WScreen->WBorLeft;
borderright = window->BorderRight;
bordertop = window->WScreen->BarHeight + 1;
borderbottom = window->BorderBottom;
/* Center the requester in the given window.
* If impossible, open a new window to the place the requester in.
*/
width = window->GZZWidth;
height = window->GZZHeight;
if (width < request->Width || height < request-> Height) {
/* Window too small. Open a new one */
newwindow.Screen = window->WScreen;
newwindow.Type = window->WScreen->Flags & SCREENTYPE;
newwindow.Title = window->Title;
newwindow.Width = request->Width + 2 * borderleft;
newwindow.Height = request->Height + bordertop + borderbottom;
newwindow.LeftEdge = (newwindow.Screen->Width - newwindow.Width) / 2;
newwindow.TopEdge = (newwindow.Screen->Height - newwindow.Height) / 2;
if (window = OpenWindow(&newwindow)) {
window->UserPort = oldwindow->UserPort;
/* Upen up the other port */
ModifyIDCMP(window, GADGETUP);
}
request->LeftEdge = borderleft;
request->TopEdge = bordertop;
} else { /* The requester fits. Center it! */
request->LeftEdge = ((width - request->Width) >> 1);
request->TopEdge = ((height - request->Height) >> 1);
if (!(window->Flags & GIMMEZEROZERO)) {
request->LeftEdge += borderleft;
request->TopEdge += bordertop;
}
}
if (window && Request(request, window)) return window;
if (window) CloseWindowSafely(window);
return NULL;
}
void EndMyRequest(request, window, original)
struct Requester *request;
struct Window *window, *original;
{
EndRequest(request, window);
if (window != original) CloseWindowSafely(window);
}
/*
* Wait on a request posted by MyRequest.
* Returns when a gadget with GadgetID >= POSGADGETID is released,
* so Gadgets with an ID < POSGADGETID will be ignored.
* NEGGADID > POSGADID.
* Any messages other than GADGETUP will be ignored.
*/
int WaitMyRequest(window)
struct Window *window;
{
int ID = 0;
struct IntuiMessage *message;
struct Gadget *Gadget;
ULONG Class;
ULONG OldIDCMP = window->IDCMPFlags;
ULONG SigMask;
if (!window)
return NEGGADGETID;
ModifyIDCMP(window, GADGETUP);
#ifdef AREXX
SigMask = RexxMask | (1L << MainWindow->UserPort->mp_SigBit);
#else
SigMask = (1L << MainWindow->UserPort->mp_SigBit);
#endif
while (ID < POSGADGETID) {
Wait(SigMask);
#ifdef AREXX
dispRexxPort();
#endif
while (message = (struct IntuiMessage *) GetMsg(window->UserPort) ) {
Class = message->Class;
Gadget = (struct Gadget *)message->IAddress;
ReplyMsg(message);
if (Class != GADGETUP) continue;
ID = Gadget->GadgetID;
if (ID >= POSGADGETID) break; /* Also gets out of outer loop */
}
}
ModifyIDCMP(window, OldIDCMP);
return ID;
}
void RectDraw(rp, x1, y1, x2, y2)
struct RastPort *rp;
SHORT x1, y1, x2,y2;
{
Move(rp, (long) x1, (long) y1);
Draw(rp, (long) x2, (long) y1);
Draw(rp, (long) x2, (long) y2);
Draw(rp, (long) x1, (long) y2);
if (y2 > y1) y1++; else y1--; /* Don't XOR the first pixel twice */
Draw(rp, (long) x1, (long) y1);
}
void CrossDraw(rp, x, y, left, right, top, bottom)
struct RastPort *rp;
SHORT x, y, top, bottom, left, right;
{
Move(rp, (long) left, (long) y);
Draw(rp, (long) right, (long) y);
Move(rp, (long) x, (long) top);
Draw(rp, (long) x, (long) bottom);
}
void DisableSystemGadgets(gadget)
struct Gadget *gadget;
{
while (gadget) {
if (gadget->GadgetType & SYSGADGET) {
/* Ghost everything except the Title/Dragbar */
if ((gadget->GadgetType & 0x00F0) != WDRAGGING)
OffGadget(gadget, MainWindow, NULL);
gadget->Flags |= GADGDISABLED;
}
gadget = gadget->NextGadget;
}
}
void EnableSystemGadgets(gadget)
struct Gadget *gadget;
{
USHORT Flags = 0;
while (gadget) {
if (gadget->GadgetType & SYSGADGET) {
Flags |= gadget->Flags;
gadget->Flags &= ~GADGDISABLED;
}
gadget = gadget->NextGadget;
}
/* Unghost everthing if necessary */
if (Flags & GADGDISABLED) RefreshWindowFrame(MainWindow);
}
void StopFraming()
{
if (MainWindow) {
EnableSystemGadgets(MainWindow->FirstGadget);
ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags & ~INTUITICKS);
}
MouseStatus = NOTFRAMING;
CloseXYwindow();
}
void CheckMouse(Message)
register struct IntuiMessage *Message;
{
register SHORT top = MainWindow->BorderTop,
bottom = MainWindow->Height - MainWindow->BorderBottom - 1,
left = MainWindow->BorderLeft,
right = MainWindow->Width - MainWindow->BorderRight - 1;
static ULONG OldSecs, OldMicros;
static SHORT MidX, MidY;
USHORT MouseX, MouseY;
if (Message->IDCMPWindow == MainWindow) {
MouseX = Message->MouseX;
MouseY = Message->MouseY;
} else {
MouseX = MainWindow->MouseX;
MouseY = MainWindow->MouseY;
}
if (StillDrawing || MouseStatus != FLASHING &&
(MouseX < left || MouseX > right || MouseY < top || MouseY > bottom))
return;
MouseX -= left;
MouseY -= top;
if (Message->Class == MOUSEBUTTONS) {
if (Message->Code == SELECTDOWN) {
/* We selected a point */
switch (MouseStatus) {
case NOTFRAMING:
case FLASHING:
MouseStatus = NOPOINT;
DisableSystemGadgets(MainWindow->FirstGadget);
ModifyIDCMP(MainWindow, MainWindow->IDCMPFlags | INTUITICKS);
OpenXYwindow();
/* Now we can select our first corner */
break;
case NOPOINT:
FrameX1 = FrameX2 = MouseX;
FrameY1 = FrameY2 = MouseY;
MouseStatus = POINT1;
OldMicros = Message->Micros;
OldSecs = Message->Seconds;
/* We have the first point. Now go for the second */
break;
case POINT1:
if (DoubleClick(OldSecs, OldMicros,
Message->Seconds, Message->Micros)) {
/* Did we double-click? Then we have selected a center */
MouseStatus = CENTERFRAMING;
MidX = FrameX1;
MidY = FrameY1;
break;
}
FrameX2 = MouseX;
FrameY2 = MouseY;
/* Fall through to CENTERFRAMING */
case CENTERFRAMING:
if (FrameX1 == FrameX2 || FrameY1 == FrameY2) break;
EnableSystemGadgets(MainWindow->FirstGadget);
MouseStatus = FLASHING;
/* Point 1 should be upper left */
if (FrameX2 < FrameX1) {
/* I DO know I am reusing a variable here. Sorry! */
left=FrameX2; FrameX2=FrameX1; FrameX1=left;
}
if (FrameY2 < FrameY1) {
left=FrameY2; FrameY2=FrameY1; FrameY1=left;
}
break;
} /* End switch MouseStatus */
} /* End if Code == SELECTDOWN */
return;
} /* End if Class == MOUSEBUTTONS */
/* We are moving the mouse. Show something! */
UpdateXYwindow(MouseX, MouseY);
SetDrMd(MainWindow->RPort, (ULONG) COMPLEMENT);
switch (MouseStatus) {
/* case NOTFRAMING: */
/* return; */
case NOPOINT:
FrameX1 = FrameX2 = MouseX;
FrameY1 = FrameY2 = MouseY;
WaitTOF();
CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
WaitTOF();
CrossDraw(MainWindow->RPort, FrameX1, FrameY1,
0, MainWindow->GZZWidth-1, 0, MainWindow->GZZHeight-1);
break;
case CENTERFRAMING:
FrameX1 = MouseX;
FrameY1 = MouseY;
FrameX2 = 2*MidX - FrameX1;
FrameY2 = 2*MidY - FrameY1;
skipto flashing;
case POINT1:
FrameX2 = MouseX;
FrameY2 = MouseY;
/* Deliberate Fall-Through to FLASHING */
case FLASHING:
flashing:
WaitTOF();
RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
WaitTOF();
RectDraw(MainWindow->RPort, FrameX1, FrameY1, FrameX2, FrameY2);
}
}
void InitPenTable()
{
register int i;
switch (PenTableMode) {
case MODULO:
PenTable[0] = 0;
for (i=1; i<MAXDEPTH; i++) PenTable[i] = 1 + i % (NumColors - 1);
break;
case RANGES:
PenTable[0] = 0;
for (i=1; i<MAXDEPTH; i++)
PenTable[i] = 1 + (i/RangeWidth) % (NumColors - 1);
case SELECT:
/* Don't change the table if it is user-defined */
break;
}
}
void SelectMenu(MenuNum, CheckIt)
LONG MenuNum;
bool CheckIt;
{
struct MenuItem *Item = ItemAddress(MandelMenu, MenuNum);
ClearMenuStrip(MainWindow);
if (CheckIt)
Item->Flags |= CHECKED;
else
Item->Flags &= ~CHECKED;
SetMenuStrip(MainWindow, MandelMenu);
}
void MakeMAND(mand)
struct Mand *mand;
{
int i;
mand->MandID = MAND;
mand->Size = sizeof(struct Mand) - 2 * sizeof(LONG);
mand->MaxDepth = MaxDepth;
mand->RangeWidth = RangeWidth;
mand->RainDist = RainbowDistance;
mand->RainRMax = RainbowRMax;
mand->RainGMax = RainbowGMax;
mand->RainBMax = RainbowBMax;
for (i=0; i < sizeof(mand->Coords); i++)
mand->Coords[i] = '\0';
sprintf(&mand->Coords[0], "%1.10g %1.10g %1.10g %1.10g",
LeftEdge, RightEdge, TopEdge, BottomEdge);
mand->FunctionNr = FunctionNr;
mand->PenTableMode = PenTableMode;
mand->WBWidth = WBWidth;
mand->WBHeight = WBHeight;
}
bool InterpretMAND(mand, ilbminfo)
struct Mand *mand;
struct ILBM_info *ilbminfo;
{
double NewLeftEdge, NewRightEdge, NewTopEdge, NewBottomEdge;
double Ratio;
/* Perform some checks on correctness of the chunk */
if (mand->MandID != MAND ||
mand->Size > sizeof(struct Mand) - 2 * sizeof(LONG) ||
mand->MaxDepth > MAXDEPTH ||
mand->RangeWidth > MAXDEPTH)
return FALSE;
if (sscanf(&mand->Coords[0], "%lf %lf %lf %lf",
&NewLeftEdge, &NewRightEdge, &NewTopEdge, &NewBottomEdge) < 4)
return FALSE;
MaxDepth = mand->MaxDepth;
RangeWidth = mand->RangeWidth;
/* Compensate for different sized windows */
Ratio = (double)MainWindow->GZZWidth / (double)ilbminfo->header.w;
LeftEdge = NewLeftEdge;
if (Ratio != 1.0)
RightEdge = NewLeftEdge + Ratio * (NewRightEdge - NewLeftEdge);
else /* avoid round-off when almost exactly 1.0000 */
RightEdge = NewRightEdge;
Ratio = (double)MainWindow->GZZHeight / (double)ilbminfo->header.h;
TopEdge = NewTopEdge;
if (Ratio != 1.0)
BottomEdge = NewTopEdge - Ratio * (NewTopEdge - NewBottomEdge);
else /* avoid round-off when almost exactly 1.0000 */
BottomEdge = NewBottomEdge;
CalcCSteps();
RainbowDistance = mand->RainDist;
RainbowRMax = mand->RainRMax;
RainbowGMax = mand->RainGMax;
RainbowBMax = mand->RainBMax;
if (mand->Size > OFFSETOF(FunctionNr, Mand) - 2*sizeof(long)) {
SetDrawingFunction(mand->FunctionNr);
PenTableMode = mand->PenTableMode;
WBWidth = mand->WBWidth;
WBHeight = mand->WBHeight;
InitPenTable();
}
UpdateCheckmarks();
return TRUE;
}